home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 163_01 / baseio1.c < prev    next >
Text File  |  1988-01-30  |  16KB  |  551 lines

  1. /*
  2. ** include baseio1.c -- base I/O routines part 1
  3. **
  4. ** simulate UNIX I/O interfaces
  5. **
  6. ** assumes that "errno.h" is included
  7. ** assumes that "sgtty.h" is included
  8. ** assumes that "doscall.h" is included
  9. ** assumes that "doscall.c" is included
  10. ** assumes that "heap.c" is included
  11. ** assumes that NUMFILES is defined
  12. */
  13.  
  14.  
  15. /*
  16. ** file descriptor (handle) array
  17. */
  18.  
  19. static int             /* would char *_filedes[] if array of * supported */
  20.   _filedes[NUMFILES];
  21.  
  22.  
  23. /*
  24. ** keyboard buffer
  25. */
  26.  
  27. static char
  28.   kbdbuf[255];
  29.  
  30.  
  31. /*
  32. ** base I/O initialization
  33. */
  34.  
  35. static _baseinit() {
  36.   int i;
  37.   i = 0;
  38.   while(i < NUMFILES) {
  39.     _filedes[i] = 0; /* clear pointer to DOS FCB in file descriptor array */
  40.     ++i;
  41.     }
  42.   kbdbuf[0]=kbdbuf[1]=0;
  43.   errno = 0;
  44.   }
  45.  
  46.  
  47. /*
  48. ** base I/O clean-up
  49. */
  50.  
  51. static _baseclnup() {
  52.   int i;
  53.   char *fcb;
  54.   i = 0;
  55.   while(i < NUMFILES) {
  56.     fcb = _filedes[i]; /* get address of DOS FCB */
  57.     if(*fcb != 0) _close(i); /* if file is open, close it */
  58.     ++i;
  59.     }
  60.   }
  61.  
  62.  
  63. /*
  64. ** open a file
  65. */
  66.  
  67. _open(name, mode) char *name; int mode; {
  68.  
  69.   /*
  70.   ** name -- path name
  71.   ** mode -- 0 - read, 1 - write, 2 - read/write
  72.   ** returns file descriptor
  73.   ** note:  always positions file to offset zero
  74.   */
  75.  
  76.   int filedes, mask;
  77.   char *fcb;
  78.   if((mode < 0) | (mode > 2)) {
  79.     errno = EINVAL;   /* invalid argument */
  80.     return -1;
  81.     }
  82.   filedes = _getfcb(name);     /* allocate & initialize DOS FCB */
  83.   if(filedes < 0) {
  84.     errno = EMFILE;   /* too many open files */
  85.     return -1;
  86.     }
  87.   fcb = _filedes[filedes];     /* get address of DOS FCB */
  88.   fcb[FCB_MODE] = mode;        /* save read/write mode */
  89.   if(mode==0)      mask=2;     /* read */
  90.   else if(mode==1) mask=1;     /* write */
  91.   else             mask=3;     /* read/write */
  92.   if((mask&fcb[FCB_FLAG])!=mask) { /* if wrong device type */
  93.     _freefcb(filedes); /* free the FCB we won't be using */
  94.     errno = ENODEV;
  95.     return -1;
  96.     }
  97.   if((fcb[FCB_FLAG]&255)==255) { /* if disk file */
  98.     if(_dosfcall(F_OPEN, fcb) == 0) { /* DOS open */
  99.       fcb[FCB_LRECL] = 1;        /* set "record length" to 1 */
  100.       fcb[FCB_LRECL+1] = 0;
  101.       fcb[FCB_FLGS] = 128 + 64 + 16;
  102.       fcb[FCB_FLGS+1] = 0;
  103.       return filedes;
  104.       }
  105.     else {
  106.       _freefcb(filedes); /* free the FCB we won't be using */
  107.       errno = ENOENT;   /* no such file */
  108.       return -1;
  109.       }
  110.     }
  111.   else {                       /* not a disk file */
  112.     if(fcb[FCB_FLAG] & 192) { /* if keyboard or screen */
  113.       fcb[FCB_FLGS] = 128 + 64 + 16 + 8;
  114.       fcb[FCB_FLGS+1] = 0;
  115.       }
  116.     else if(fcb[FCB_FLAG] & 32) { /* if printer */
  117.       fcb[FCB_FLGS] = 16;
  118.       fcb[FCB_FLGS+1] = 0;
  119.       }
  120.     else if(fcb[FCB_FLAG] & 16) { /* if async */
  121.       fcb[FCB_FLGS] = 128 + 64 + 32;
  122.       fcb[FCB_FLGS+1] = 0;
  123.       }
  124.     return filedes;
  125.     }
  126.   }
  127.  
  128.  
  129. /*
  130. ** create and open a file (or reopen if existing)
  131. */
  132.  
  133. _creat(name, mode) char *name; int mode; {
  134.  
  135.   /*
  136.   ** name -- path name
  137.   ** mode -- file attributes -- 0 - normal, 2 - system, 4 hidden
  138.   ** returns file descriptor
  139.   ** note:  always positions file to offset zero
  140.   ** note:  file is always opened for write
  141.   */
  142.  
  143.   int filedes;
  144.   char *fcb;
  145.   if((mode < 0) | (mode > 2)) {
  146.     errno = EINVAL;   /* invalid argument */
  147.     return -1;
  148.     }
  149.   filedes = _getfcb(name);     /* allocate & initialize DOS FCB */
  150.   if(filedes < 0) {
  151.     errno = EMFILE;   /* too many open files */
  152.     return -1;
  153.     }
  154.   fcb = _filedes[filedes];     /* get address of DOS FCB */
  155.   if((fcb[FCB_FLAG]&255)!=255) { /* if not a disk file */
  156.     _freefcb(filedes); /* free the FCB we won't be using */
  157.     return _open(name, 1);     /* use normal open for write */
  158.     }
  159.   fcb[FCB_ATTR] = mode;        /* set file attributes */
  160.   if(_dosfcall(F_CREATE, fcb) == 0) {       /* DOS create & open */
  161.     fcb[FCB_LRECL] = 1;        /* set "record length" to 1 */
  162.     fcb[FCB_LRECL+1] = 0;
  163.     fcb[FCB_FLGS] = 128 + 64 + 16;
  164.     fcb[FCB_FLGS+1] = 0;
  165.     fcb[FCB_MODE] = 1;         /* write only */
  166.     return filedes;
  167.     }
  168.   else {
  169.     _freefcb(filedes); /* free the FCB we won't be using */
  170.     errno = ENOSPC;   /* no space in disk directory */
  171.     return -1;
  172.     }
  173.   }
  174.  
  175.  
  176. /*
  177. ** close a file
  178. */
  179.  
  180. _close(filedes) int filedes; {
  181.   char *fcb;
  182.   int *ibuf;
  183.   if((filedes >= NUMFILES) | (filedes < 0)) {
  184.     errno = EINVAL;   /* invalid argument */
  185.     return -1;
  186.     }
  187.   fcb = _filedes[filedes];     /* get address of DOS FCB */
  188.   if(fcb[FCB_FLAG] == 0) {
  189.     errno = EBADF;    /* bad file number -- file not open */
  190.     return -1;
  191.     }
  192.   if((fcb[FCB_FLAG]&255) == 255) { /* if file is standard disk file */
  193.     /* if file is DOS format output (only) file, add the ctl-Z (end-of-file) */
  194.     if((fcb[FCB_FLGS]&16) && (fcb[FCB_MODE]&1)) {
  195.       _seek(filedes, 0, 5); /* find end of file */
  196.       _write(filedes, "\32", 1); /* add ctl-Z */
  197.       _iflush(fcb); /* if there is an intermediate buf, flush (ignore errors) */
  198.       ibuf = &fcb[FCB_IBUF];
  199.       if(*ibuf) free(*ibuf); /* free intermediate buffer (if any) */
  200.       }
  201.     if(_dosfcall(F_CLOSE, fcb) == 0) { /* DOS close */
  202.       _freefcb(filedes); /* free the DOS FCB */
  203.       return 0;
  204.       }
  205.     else {
  206.       errno = ENXIO; /* wrong disk may be mounted */
  207.       return -1;
  208.       }
  209.     }
  210.   else {
  211.     if(fcb[FCB_FLAG] & 32) { /* if printer */
  212.       _prnout('\f');
  213.       }
  214.     _freefcb(filedes); /* free the DOS FCB */
  215.     return 0;
  216.     }
  217.   }
  218.  
  219.  
  220. /*
  221. ** read from a file
  222. */
  223.  
  224. _read(filedes, buffer, nbytes) int filedes, nbytes; char *buffer; {
  225.   char *fcb, ch, mode, *source, *dest;
  226.   int rcode, rbytes, count;
  227.   if((filedes >= NUMFILES) | (filedes < 0)) {
  228.     errno = EINVAL;   /* invalid argument */
  229.     return -1;
  230.     }
  231.   if(nbytes <= 0) {
  232.     errno = EINVAL;   /* invalid argument */
  233.     return -1;
  234.     }
  235.   fcb = _filedes[filedes];     /* get address of DOS FCB */
  236.   if(fcb[FCB_FLAG] == 0) {
  237.     errno = EBADF;    /* bad file number -- file not open */
  238.     return -1;
  239.     }
  240.   if(fcb[FCB_MODE] & 128) {  /* if end-of-file exists */
  241.     return 0;        /* report end-of-file */
  242.     }
  243.   if((fcb[FCB_FLAG]&255) == 255) { /* if file is standard disk file */
  244.     if(fcb[FCB_MODE] & 1) {    /* if not read-mode file */
  245.       errno = EBADF;  /* bad file number -- file not read-mode */
  246.       return -1;
  247.       }
  248.     _dosfcall(F_SETDTA, buffer);    /* set disk transfer area */
  249.     rcode = _dosfxcall(F_READ, fcb, nbytes, &rbytes); /* read the file */
  250.     if(rcode==2) {
  251.       errno = EFAULT; /* bad address range (segment wrap) */
  252.       return -1;
  253.       }
  254.     if((rcode==1) | (rcode==3)) {       /* if end-of-file */
  255.       fcb[FCB_MODE] |= 128;    /* remember end-of-file for next call */
  256.       }
  257.     if(fcb[FCB_FLGS] & 16) { /* if CR-LF conversion */
  258.       source = buffer;
  259.       dest = buffer;
  260.       count = rbytes;
  261.       rbytes = 0;
  262.       mode = fcb[FCB_MODE];
  263.       while(count--) {
  264.         if(*source == '\32') { /* check for ctl-Z (EOF) */
  265.           fcb[FCB_MODE] |= 128; /* set EOF flag */
  266.           break;
  267.           }
  268.         else if(*source == '\r') { /* check for CR */
  269.           if(mode & 32) { /* if prior char was LF */
  270.             mode &= ~32; /* ignore the CR */
  271.             }
  272.           else { /* prior char was not LF */
  273.             *dest++ = '\n'; /* convert CR to LF */
  274.             ++rbytes;
  275.             mode |= 64; /* ignore possible following LF */
  276.             }
  277.           }
  278.         else if(*source == '\n') { /* check for LF */
  279.           if(mode & 64) { /* if prior char was CR */
  280.             mode &= ~64; /* ignore the LF */
  281.             }
  282.           else { /* prior char was not CR */
  283.             *dest++ = '\n'; /* "convert" LF to LF */
  284.             ++rbytes;
  285.             mode |= 32; /* ignore possible following CR */
  286.             }
  287.           }
  288.         else{ /* none of the above */
  289.           *dest++ = *source; /* copy the character */
  290.           ++rbytes;
  291.           mode &= ~(64 + 32); /* turn off CR and LF flags */
  292.